import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

abstract class Element extends JPanel implements MouseListener,
		MouseMotionListener {

	protected int width, height;

	protected int statWidth, statHeight,maxWidth,maxHeight;
	protected String text;
	protected boolean dragFlag, selected;
	protected boolean reszFlag;
	protected int x0, y0;
	protected int maxInputCount, maxOutputCount;
	private int inputCount, outputCount;
	protected GridPanel parent;

	public Element(String text, int x, int y, GridPanel parent) {
		this.text = text;
		this.parent = parent;
		dragFlag = false;
		setLocation(x, y);
		addMouseListener(this);
		addMouseMotionListener(this);
		setOpaque(false);
		inputCount = 0;
		outputCount = 0;
	}

	public void setText(String s) {
		text = s;
	}

	public void borderExitFix() {

		if (getX() > getParent().getWidth() - getWidth()) {
			dragFlag = false;
			setLocation(parent.round(parent.getWidth() - getWidth()), getY());
		}
		if (getX() < 0) {
			dragFlag = false;
			setLocation(0, getY());
		}
		if (getY() > getParent().getHeight() - getHeight()) {
			dragFlag = false;
			setLocation(getX(), parent.round(parent.getHeight() - getHeight()));
		}
		if (getY() < 0) {
			dragFlag = false;
			setLocation(getX(), 0);
		}
	}

	private void locateToGrid() {
		setLocation(parent.round(getX()), parent.round(getY()));
	}

	public void mouseDragged(MouseEvent e) {
		if (dragFlag) {
			setLocation(getX() + parent.round(e.getX() - x0),
					getY() + parent.round(e.getY() - y0));
			borderExitFix();
			locateToGrid();
		} else if (reszFlag) {
			if ((e.getX() > statWidth)
					&& (getX() + e.getX() < getParent().getWidth())
					&& (e.getX() < maxWidth))
				width = parent.round(e.getX());
			if ((e.getY() > statHeight)
					&& ((getY() + e.getY()) < getParent().getHeight())
					&& (e.getY() < maxHeight))
				height = parent.round(e.getY());

			this.setSize(width, height);

		}
	}

	public void mousePressed(MouseEvent e) {

		if (parent.getAction() == GridPanel.ActionType.DRAW_ARROW) {
			if (!parent.drawingArrow() && canAddOutput()
					|| (parent.drawingArrow() && canAddInput()))
				parent.elementSelected(this);
		} else {
			x0 = e.getX();
			y0 = e.getY();

			if ((e.getX() > getWidth() - 6) && (e.getY() > getHeight() - 6))
				reszFlag = true;
			// else if ((e.getX() > getWidth() - 6) && (e.getY() < 6)) {
			// tmpResz = true;
			// }
			else {
				dragFlag = true;
				reszFlag = false;
			}
		}
	}

	public void mouseReleased(MouseEvent e) {
		dragFlag = false;
		repaint(0);
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
	}

	public void mouseMoved(MouseEvent e) {
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
		this.selected = true;
		repaint();
	}

	public void mouseExited(MouseEvent e) {
		this.selected = false;
		repaint();
	}

	public boolean canAddInput() {
		return maxInputCount == -1 || inputCount < maxInputCount;
	}

	public boolean canAddOutput() {
		return maxOutputCount == -1 || outputCount < maxOutputCount;
	}

	public void addInput() {
		inputCount++;
	}

	public void addOutput() {
		outputCount++;
	}

	public void removeInput() {
		inputCount--;
	}

	public void removeOutput() {
		outputCount--;
	}

	public int getBottom() {
		return getY() + getHeight();
	}

	public int getRight() {
		return getX() + getWidth();
	}

	public int getCenterX() {
		return getX() + getWidth() / 2;
	}

	public int getCenterY() {
		return getY() + getHeight() / 2;
	}
}
